package com.scse.bms.web.admin;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSONObject;
import com.scse.bms.config.AppConfig;
import com.scse.bms.domain.BookCaseVO;
import com.scse.bms.domain.BookVO;
import com.scse.bms.domain.ThemeVO;
import com.scse.bms.entity.BookDO;
import com.scse.bms.entity.EBookDO;
import com.scse.bms.entity.ThemeDO;
import com.scse.bms.entity.TypeDO;
import com.scse.bms.service.BookService;
import com.scse.bms.service.ThemeService;
import com.scse.bms.service.TypeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.sql.Timestamp;
import java.util.Date;
import java.util.List;

/**
 * @Title: BookController
 * @Author: 吴赠禹
 * @Date: 2021/1/11 13:50
 * @Version: 1.0
 * @Description: TODO
 */

@Slf4j
@Controller
public class BookController {

    @Resource
    private AppConfig appConfig;

    @Autowired
    @Qualifier("bookService")
    private BookService bookService;

    @Autowired
    @Qualifier("typeService")
    private TypeService typeService;

    @Autowired
    private ThemeService themeService;

    /**
     * 多文件上传接口（pdf）
     *
     * @param file
     * @return
     */
    @ResponseBody
    @PostMapping("/book/multi/upload")
    public String multiUpload(@RequestParam("file") MultipartFile file) {
        log.info("[multiUpload] 多本pdf上传");
        String path = "";
        // 默认文件上传成功，并返回状态信息
        // 获取文件名以及后缀名
        String fileName = file.getOriginalFilename();
        // 时间戳+三位随机字串生成文件名
        String prefix = DateUtil.format(new Date(), "yyyyMMddHHmmsssss") + RandomUtil.randomString(3);
        fileName = prefix + "_" + fileName;
        // 指定上传文件本地存储目录，不存在则需要提前创建
        String dirPath = appConfig.getPdfDir();
        createIfNoExists(dirPath);
        path = dirPath + fileName;
        try {
            // 插入数据库
            addEbook(path, file);
            file.transferTo(new File(dirPath + fileName));
        } catch (Exception e) {
            log.info(e.getMessage());
        }
        // 携带上传状态信息回调到文件上传页面
        return getJsonRes(0, "success", path);
    }

    /**
     * 只负责上传图片
     * @param file
     * @return
     */
    @ResponseBody
    @PostMapping("/book/upload/img")
    public String uploadImage(@RequestParam("file") MultipartFile file) {
        log.info("[uploadImage] 上传电子书封面");
        String fileName = file.getOriginalFilename();
        // 指定存储目录
        String dirPath = appConfig.getImgDir();
        createIfNoExists(dirPath);
        try {
            file.transferTo(new File(dirPath + fileName));
        } catch (Exception e) {
            log.info(e.getMessage());
        }
        return getJsonRes(0, "success", dirPath + fileName);
    }


    /**
     * 上传电子书
     * @param file
     * @return
     */
    @ResponseBody
    @PostMapping("/book/upload/pdf")
    public String uploadPDF(@RequestParam("file") MultipartFile file) {
        log.info("[uploadPDF] 上传电子书pdf");
        String fileName = file.getOriginalFilename();
        // 指定存储目录
        String dirPath = appConfig.getPdfDir();
        createIfNoExists(dirPath);
        String date = null;
        long size = file.getSize();
        try {
            file.transferTo(new File(dirPath + fileName));
            date = DateUtil.formatDateTime(new Date());
        } catch (Exception e) {
            log.info(e.getMessage());
        }
        return getJsonRes(0, "success", dirPath + fileName, date, size);
    }


    /**
     * 去修改电子书页面
     * @param id
     * @param model
     * @return
     */
    @GetMapping("/book/edit")
    public String toEditPage(@RequestParam("id") Integer id, Model model) {
        BookDO book = bookService.selectBook(id);
        model.addAttribute("book", book);
        // 页面要显示所有的分类
        List<TypeDO> typeList = typeService.selectAll();
        model.addAttribute("items", typeList);
        List<ThemeVO> themeList = themeService.list();
        model.addAttribute("themes", themeList);
        return "/back/book/uploadSingle";
    }

    /**
     * 跳转页面之前获取书籍类型
     * 返回的页面可以正确显示在iframe中（main）
     * @param model
     * @return
     */
    @GetMapping("/admin/uploadSingle")
    public String getAllTypeBeforeUpload(Model model) {
        List<TypeDO> list = typeService.selectAll();
        model.addAttribute("items", list);
        log.info("[getAllTypeBeforeUpload] 获取中图分类：{}", list);
        List<ThemeVO> themeList = themeService.list();
        model.addAttribute("themes", themeList);
        log.info("[getAllTypeBeforeUpload] 获取主题分类：{}",themeList);
        return "/back/book/uploadSingle";
    }


    @PostMapping("/api/deleBook")
    @ResponseBody
    public String deleBook(@RequestBody BookDO book) {

        log.info("[deleBook] 删除一条记录：{}", book);
        int result = bookService.removeBook(book);
        if (result > 0) {
            return getJsonRes(0, "suc");
        } else {
            return getJsonRes(-1, "err");
        }
    }


    /**
     * 修改图书记录
     * @param book
     * @return
     */
    @PostMapping("/api/editBook")
    @ResponseBody
    public String editBook(@RequestBody BookDO book) {
        log.info("[editBook] 修改图书记录：{}" , book);
        int result = bookService.updateBook(book);
        if (result > 0) {
            return getJsonRes(0, "success");
        } else {
            return getJsonRes(-1, "error");
        }
    }


    /**
     * ajax接口：添加图书
     * @param book
     * @return
     */
    @PostMapping("/api/addBook")
    @ResponseBody
    public String addBook(@RequestBody BookDO book) {
        log.info("[addBook] 准备添加一条图书记录：" + book.toString());
        // res 表示受影响行数
        int res = bookService.addBook(book);
        String json = null;
        if (res > 0) {
            json = getJsonRes(0, "success");
            log.info(String.format("[addBook] 添加成功，编号：%s，书名：%s", book.getId(), book.getTitle()));
        } else {
            json = getJsonRes(-1, "error");
            log.info("[addBook] 添加记录失败！");
        }
        return json;
    }

    /**
     * 创建文件目录
     * @param dir
     */
    private void createIfNoExists(String dir) {
        File filePath = new File(dir);
        if (!filePath.exists()) {
            filePath.mkdirs();
        }
    }


    /**
     * 返回JSON字串结果[code, msg]
     * @param code
     * @param msg
     * @return
     */
    private String getJsonRes(int code, String msg) {
        JSONObject object = new JSONObject();
        object.put("code", code);
        object.put("msg", msg);
        return object.toJSONString();
    }

    /**
     * 返回JSON结果
     * @param code
     * @param msg
     * @param dir
     * @return
     */
    private String getJsonRes(int code, String msg, String dir) {
        JSONObject object = new JSONObject();
        object.put("code", code);
        object.put("msg", msg);
        object.put("dir", dir);
        return object.toJSONString();
    }

    private String getJsonRes(int code, String msg, String dir, String uploadTime, long size) {
        JSONObject object = new JSONObject();
        object.put("code", code);
        object.put("msg", msg);
        object.put("dir", dir);
        object.put("time", uploadTime);
        object.put("size", size);
        return object.toJSONString();
    }

    /**
     * 添加电子书记录到数据库
     *
     * @param path
     * @param file
     */
    private void addEbook(String path, MultipartFile file) {
        log.info("[addEbook] 添加电子书记录");
        EBookDO book = new EBookDO();
        book.setSrc(path);
        book.setSize(file.getSize());
        book.setUploadTime(new Timestamp(System.currentTimeMillis()));
        String title = file.getOriginalFilename();
        book.setTitle(title.substring(0, title.indexOf(".pdf")));
        log.info("插入的ebook:" + book.toString());
        bookService.addEBook(book);
    }

    @GetMapping("/book/type")
    @ResponseBody
    public String getBookType() {
        log.info("[getBookType] 获取图书的中图分类");
        List<TypeDO> types = typeService.selectAll();
        JSONObject object = new JSONObject();
        object.put("data", types);
        return object.toJSONString();
    }


    /**
     * layui数据表格获取数据渲染（页面加载时自动发起get请求）
     * @param page
     * @param limit
     * @return
     */
    @GetMapping("/book/all")
    @ResponseBody
    public String getAllBook(@RequestParam(required = false, defaultValue = "1") Integer page,
                             @RequestParam(required = false, defaultValue = "15") Integer limit) {
        log.info("[getAllBook] 获取所有图书记录");
        // 获取记录总数（必需，用于前端分页，否则仅显示1页）
        int count = bookService.countAll();
        // 移动记录指针（数据下标从0开始）
        int pageIndex = (page - 1) * limit;
        List<BookVO> books = bookService.selectAll(pageIndex, limit);
        // 返回符合layUI数据表格解析的格式
        JSONObject json = new JSONObject();
        // code必须为0，否则导致渲染失败（也可以自定义）
        json.put("code", 0);
        json.put("msg", "查询成功");
        json.put("count", count);
        json.put("data", books);
        return json.toString();
    }

    @PostMapping("/book/all")
    @ResponseBody
    public String getAllBookByCase(@RequestBody BookCaseVO book) {
        log.info("[getAllBookByCase] 条件查询分页：{}", book);
        // TODO 符合条件的记录数
        // int count = bookService.countByCase(book);
        // 增加推荐状态查询条件后，要从list中获取总记录数
        int count = bookService.countBookByCase(book).size();
        // 从哪里开始取（下标从0开始，所以-1）
        int pageIndex = (book.getPage() - 1) * book.getLimit();
        book.setPage(pageIndex);
        List<BookVO> books = bookService.getBookByCase(book);
        log.info("[getAllBookByCase] 获取的数据：\n" + books.toString());
        JSONObject json = new JSONObject();
        json.put("code", 0);
        json.put("msg", "success");
        json.put("count", count);
        json.put("data", books);
        return json.toString();
    }


    public static void main(String[] args) {
        String name = null;
        System.out.println(name.substring(0, name.indexOf(".pdf")));
    }

}
